package com.tianxiao.faas.biz.corner.service.user;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.qcloud.cos.utils.Md5Utils;
import com.tianxiao.faas.api.param.corner.LoginResult;
import com.tianxiao.faas.biz.domain.entity.UserExt;
import com.tianxiao.faas.biz.service.corner.UserLogService;
import com.tianxiao.faas.common.exception.biz.BizException;
import com.tianxiao.faas.common.util.DateUtils;
import com.tianxiao.faas.common.util.StringUtils;
import com.tianxiao.faas.common.util.UUIDUtils;
import com.tianxiao.faas.mapper.dao.LoginInfoModelMapper;
import com.tianxiao.faas.mapper.dao.ThirdPartInfoModelMapper;
import com.tianxiao.faas.mapper.model.LoginInfoModel;
import com.tianxiao.faas.mapper.model.LoginInfoModelExample;
import com.tianxiao.faas.mapper.model.ThirdPartInfoModel;
import com.tianxiao.faas.mapper.model.ThirdPartInfoModelExample;
import com.tianxiao.faas.mapper.model.UsersModel;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;

@Service
public class UserLoginService {

    @Resource
    private LoginInfoModelMapper loginInfoModelMapper;
    @Resource
    private UserService userService;
    @Resource
    private ThirdPartInfoModelMapper thirdPartInfoModelMapper;
    @Resource
    private UserLogService userLogService;

    @Transactional(rollbackFor = Throwable.class)
    public LoginResult wxLogin(String rawData, JSONObject sessionKeyOpenId) {
        JSONObject rawDataJson = JSON.parseObject(rawData);
        String openid = sessionKeyOpenId.getString("openid");
        if (StringUtils.isEmpty(openid)) {
            throw new BizException("微信信息获取异常");
        }
        String unionid = sessionKeyOpenId.getString("unionid");
        ThirdPartInfoModelExample example = new ThirdPartInfoModelExample();
        example.createCriteria().andThirdPartIdEqualTo(openid).andDeletedEqualTo(0);
        List<ThirdPartInfoModel> thirdPartInfoModels =
                thirdPartInfoModelMapper.selectByExample(example);
        String avatarUrl = rawDataJson.getString("avatarUrl");
        avatarUrl = avatarUrl == null ? "https://cdn.cornsee.com/static/be1a1194-db9c-43a9-8d36-77613bd7bc77.png" : avatarUrl;
        String nickName = rawDataJson.getString("nickName");
        nickName = StringUtils.isEmpty(nickName) ? "Corner" +DateUtils.rankName() : nickName;
        String thirdPartId = sessionKeyOpenId.toJSONString();
        String token = null;
        LoginResult loginResult = new LoginResult();
        if (!CollectionUtils.isEmpty(thirdPartInfoModels)) {
            ThirdPartInfoModel thirdPartInfoModel = thirdPartInfoModels.get(0);
            Long userId = thirdPartInfoModel.getUserId();
            thirdPartInfoModel.setThirdPartId(thirdPartId);
            LoginInfoModel loginInfoModel = checkAndLogin(userId);
            UsersModel user = userService.getById(userId);
            if (StringUtils.isEmpty(user.getImg()) && avatarUrl != null) {
                user.setImg(avatarUrl);
            }
            if (nickName != null) {
                user.setNickname(nickName);
            }
            String valueBox = user.getValueBox();
            UserExt userExt;
            if (valueBox != null) {
                userExt = JSONObject.parseObject(valueBox, UserExt.class);
            } else {
                userExt = new UserExt();
            }
            userExt.setWxInfo(rawData);
            userService.update(user);
            token = loginInfoModel.getToken();
            buildLoginResult(avatarUrl, token, loginResult, user);
            userLogService.log(userId, "wx_login", sessionKeyOpenId.toJSONString());
        } else {
            UsersModel usersModel = userService.insert(nickName, avatarUrl, rawData);
            ThirdPartInfoModel record = new ThirdPartInfoModel();
            record.setThirdPartId(openid);
            Long userId = usersModel.getId();
            record.setUserId(userId);
            long created = System.currentTimeMillis();
            record.setCreated(created);
            record.setUpdated(created);
            record.setDeleted(0);
            record.setThirdInfo(thirdPartId);
            record.setUnionId(unionid);
            thirdPartInfoModelMapper.insertSelective(record);
            LoginInfoModel loginInfoModel = checkAndLogin(userId);
            token = loginInfoModel.getToken();
            buildLoginResult(avatarUrl, token, loginResult, usersModel);
            userLogService.log(userId, "wx_login", sessionKeyOpenId.toJSONString());
        }

        return loginResult;
    }

    private void buildLoginResult(String avatarUrl, String token, LoginResult loginResult, UsersModel usersModel) {
        loginResult.setToken(token);
        loginResult.setAvatar(avatarUrl);
        loginResult.setName(usersModel.getName());
        loginResult.setId(usersModel.getId());
        loginResult.setNickName(usersModel.getNickname());
        loginResult.setMobile(usersModel.getMobile());
    }

    public void register(String mobile, String name, String passwd, String img, List<String> access) {
        userService.insert(mobile, name, passwd, img, access);
    }

    public LoginInfoModel login(String mobile, String passwd) {
        UsersModel byMobile = userService.getByMobile(mobile);
        if (byMobile == null) {
            throw new BizException("账户名/密码错误.");
        }
        Long userId = byMobile.getId();
        String valueBox = byMobile.getValueBox();
        if (StringUtils.isEmpty(valueBox)) {
            throw new BizException("账户名/密码错误。");
        }
        UserExt userExt = JSONObject.parseObject(valueBox, UserExt.class);
        String passwd1 = userExt.getPasswd();
        String s = Md5Utils.md5Hex(passwd);
        if (!passwd1.equals(s)) {
            throw new BizException("账户名/密码错误");
        }
        return checkAndLogin(userId);
    }

    public LoginInfoModel checkAndLogin(Long userId) {
        LoginInfoModel loginInfoByUserId = getLoginInfoByUserId(userId);
        if (loginInfoByUserId != null && StringUtils.isNotEmpty(loginInfoByUserId.getToken())) {
            return loginInfoByUserId;
        }
        if (loginInfoByUserId != null) {
            loginInfoByUserId.setToken(UUIDUtils.newUUID());
            loginInfoByUserId.setUpdated(System.currentTimeMillis());
            loginInfoModelMapper.updateByPrimaryKeySelective(loginInfoByUserId);
            return loginInfoByUserId;
        }
        LoginInfoModel loginInfoModel = new LoginInfoModel();
        long currentTimeMillis = System.currentTimeMillis();
        loginInfoModel.setCreated(currentTimeMillis);
        loginInfoModel.setUpdated(currentTimeMillis);
        loginInfoModel.setDeleted(0);
        loginInfoModel.setUserId(userId);
        loginInfoModel.setLoginTime(currentTimeMillis);
        loginInfoModel.setToken(UUIDUtils.newUUID());
        loginInfoModelMapper.insertSelective(loginInfoModel);
        return loginInfoModel;
    }

    public LoginInfoModel logout(String token) {
        LoginInfoModel loginInfoModel = getLoginInfoModel(token);
        loginInfoModel.setToken("");
        loginInfoModel.setUpdated(System.currentTimeMillis());
        loginInfoModelMapper.updateByPrimaryKeySelective(loginInfoModel);
        return loginInfoModel;
    }

    public Long getLoginUserId(String token) {
        if (token == null) {
            return null;
        }
        LoginInfoModel loginInfoModel = getLoginInfoModel(token);
        if (loginInfoModel == null) return null;
        return loginInfoModel.getUserId();
    }

    public LoginInfoModel getLoginInfoByUserId(Long userId) {
        LoginInfoModelExample example = new LoginInfoModelExample();
        example.createCriteria().andUserIdEqualTo(userId).andDeletedEqualTo(0);
        List<LoginInfoModel> loginInfoModels = loginInfoModelMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(loginInfoModels)) {
            return null;
        }
        LoginInfoModel loginInfoModel = loginInfoModels.get(0);
        return loginInfoModel;
    }

    public LoginInfoModel getLoginInfoModel(String token) {
        LoginInfoModelExample example = new LoginInfoModelExample();
        example.createCriteria().andTokenEqualTo(token).andDeletedEqualTo(0);
        List<LoginInfoModel> loginInfoModels = loginInfoModelMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(loginInfoModels)) {
            return null;
        }
        LoginInfoModel loginInfoModel = loginInfoModels.get(0);
        return loginInfoModel;
    }
}
